+2001-03-21 Alexander Larsson <alexl@redhat.com>
+
+ * gtk/gtkbutton.[ch]:
+ * gtk/gtkdialog.c:
+ Renamed gtk_button_new_stock() to gtk_button_new_from_stock() and
+ removed accel_group argument. Renamed gtk_button_new_accel() to
+ gtk_button_new_with_mnemonic() and removed accel_group argument.
+
+ * gtk/gtkcheckbutton.[ch]:
+ New function gtk_check_button_new_with_mnemonic().
+
+ * gtk/gtkentry.c:
+ Override activate_mnemonic and just grab focus.
+
+ * gtk/gtkitemfactory.c:
+ Don't add menu uline accel group, instead use mnemonics support.
+
+ * gtk/gtklabel.[ch]:
+ New support for mnemonics.
+
+ * gtk/gtkmarshal.list:
+ Needed BOOLEAN:BOOLEAN for activate_mnemonic.
+
+ * gtk/gtkmenu.[c]:
+ * gtkmenushell.c:
+ Use mnemonics instead of accel groups for uline
+ support in menu items.
+ Removed gtk_menu_get_uline_accel_group() and
+ gtk_menu_ensure_uline_accel_group().
+
+ * gtk/gtkmenuitem.c:
+ Override activate_mnemonic to handle switching between
+ menu items if there are collisions.
+
+ * gtk/gtknotebook.c:
+ Connect to activate_mnemonic on the tab_label, so that
+ activating it switches to that notebook page.
+
+ * gtk/gtkwidget.[ch]:
+ Add activate_mnemonic signal. New function
+ gtk_widget_activate_mnemonic() to emit it.
+ Default implementation does activate/grab_focus.
+
+ * gtk/gtkwindow.[ch]:
+ Add support for mnemonics in windows.
+ New functions:
+ gtk_window_add_mnemonic, gtk_window_remove_mnemonic,
+ gtk_window_activate_mnemonic, gtk_window_set_mnemonic_modifier
+
+ * gtk/testgtk.c:
+ Update to function name changes.
+
2001-03-21 Alexander Larsson <alexl@redhat.com>
* gtk/gtkimagemenuitem.[c]:
+2001-03-21 Alexander Larsson <alexl@redhat.com>
+
+ * gtk/gtkbutton.[ch]:
+ * gtk/gtkdialog.c:
+ Renamed gtk_button_new_stock() to gtk_button_new_from_stock() and
+ removed accel_group argument. Renamed gtk_button_new_accel() to
+ gtk_button_new_with_mnemonic() and removed accel_group argument.
+
+ * gtk/gtkcheckbutton.[ch]:
+ New function gtk_check_button_new_with_mnemonic().
+
+ * gtk/gtkentry.c:
+ Override activate_mnemonic and just grab focus.
+
+ * gtk/gtkitemfactory.c:
+ Don't add menu uline accel group, instead use mnemonics support.
+
+ * gtk/gtklabel.[ch]:
+ New support for mnemonics.
+
+ * gtk/gtkmarshal.list:
+ Needed BOOLEAN:BOOLEAN for activate_mnemonic.
+
+ * gtk/gtkmenu.[c]:
+ * gtkmenushell.c:
+ Use mnemonics instead of accel groups for uline
+ support in menu items.
+ Removed gtk_menu_get_uline_accel_group() and
+ gtk_menu_ensure_uline_accel_group().
+
+ * gtk/gtkmenuitem.c:
+ Override activate_mnemonic to handle switching between
+ menu items if there are collisions.
+
+ * gtk/gtknotebook.c:
+ Connect to activate_mnemonic on the tab_label, so that
+ activating it switches to that notebook page.
+
+ * gtk/gtkwidget.[ch]:
+ Add activate_mnemonic signal. New function
+ gtk_widget_activate_mnemonic() to emit it.
+ Default implementation does activate/grab_focus.
+
+ * gtk/gtkwindow.[ch]:
+ Add support for mnemonics in windows.
+ New functions:
+ gtk_window_add_mnemonic, gtk_window_remove_mnemonic,
+ gtk_window_activate_mnemonic, gtk_window_set_mnemonic_modifier
+
+ * gtk/testgtk.c:
+ Update to function name changes.
+
2001-03-21 Alexander Larsson <alexl@redhat.com>
* gtk/gtkimagemenuitem.[c]:
+2001-03-21 Alexander Larsson <alexl@redhat.com>
+
+ * gtk/gtkbutton.[ch]:
+ * gtk/gtkdialog.c:
+ Renamed gtk_button_new_stock() to gtk_button_new_from_stock() and
+ removed accel_group argument. Renamed gtk_button_new_accel() to
+ gtk_button_new_with_mnemonic() and removed accel_group argument.
+
+ * gtk/gtkcheckbutton.[ch]:
+ New function gtk_check_button_new_with_mnemonic().
+
+ * gtk/gtkentry.c:
+ Override activate_mnemonic and just grab focus.
+
+ * gtk/gtkitemfactory.c:
+ Don't add menu uline accel group, instead use mnemonics support.
+
+ * gtk/gtklabel.[ch]:
+ New support for mnemonics.
+
+ * gtk/gtkmarshal.list:
+ Needed BOOLEAN:BOOLEAN for activate_mnemonic.
+
+ * gtk/gtkmenu.[c]:
+ * gtkmenushell.c:
+ Use mnemonics instead of accel groups for uline
+ support in menu items.
+ Removed gtk_menu_get_uline_accel_group() and
+ gtk_menu_ensure_uline_accel_group().
+
+ * gtk/gtkmenuitem.c:
+ Override activate_mnemonic to handle switching between
+ menu items if there are collisions.
+
+ * gtk/gtknotebook.c:
+ Connect to activate_mnemonic on the tab_label, so that
+ activating it switches to that notebook page.
+
+ * gtk/gtkwidget.[ch]:
+ Add activate_mnemonic signal. New function
+ gtk_widget_activate_mnemonic() to emit it.
+ Default implementation does activate/grab_focus.
+
+ * gtk/gtkwindow.[ch]:
+ Add support for mnemonics in windows.
+ New functions:
+ gtk_window_add_mnemonic, gtk_window_remove_mnemonic,
+ gtk_window_activate_mnemonic, gtk_window_set_mnemonic_modifier
+
+ * gtk/testgtk.c:
+ Update to function name changes.
+
2001-03-21 Alexander Larsson <alexl@redhat.com>
* gtk/gtkimagemenuitem.[c]:
+2001-03-21 Alexander Larsson <alexl@redhat.com>
+
+ * gtk/gtkbutton.[ch]:
+ * gtk/gtkdialog.c:
+ Renamed gtk_button_new_stock() to gtk_button_new_from_stock() and
+ removed accel_group argument. Renamed gtk_button_new_accel() to
+ gtk_button_new_with_mnemonic() and removed accel_group argument.
+
+ * gtk/gtkcheckbutton.[ch]:
+ New function gtk_check_button_new_with_mnemonic().
+
+ * gtk/gtkentry.c:
+ Override activate_mnemonic and just grab focus.
+
+ * gtk/gtkitemfactory.c:
+ Don't add menu uline accel group, instead use mnemonics support.
+
+ * gtk/gtklabel.[ch]:
+ New support for mnemonics.
+
+ * gtk/gtkmarshal.list:
+ Needed BOOLEAN:BOOLEAN for activate_mnemonic.
+
+ * gtk/gtkmenu.[c]:
+ * gtkmenushell.c:
+ Use mnemonics instead of accel groups for uline
+ support in menu items.
+ Removed gtk_menu_get_uline_accel_group() and
+ gtk_menu_ensure_uline_accel_group().
+
+ * gtk/gtkmenuitem.c:
+ Override activate_mnemonic to handle switching between
+ menu items if there are collisions.
+
+ * gtk/gtknotebook.c:
+ Connect to activate_mnemonic on the tab_label, so that
+ activating it switches to that notebook page.
+
+ * gtk/gtkwidget.[ch]:
+ Add activate_mnemonic signal. New function
+ gtk_widget_activate_mnemonic() to emit it.
+ Default implementation does activate/grab_focus.
+
+ * gtk/gtkwindow.[ch]:
+ Add support for mnemonics in windows.
+ New functions:
+ gtk_window_add_mnemonic, gtk_window_remove_mnemonic,
+ gtk_window_activate_mnemonic, gtk_window_set_mnemonic_modifier
+
+ * gtk/testgtk.c:
+ Update to function name changes.
+
2001-03-21 Alexander Larsson <alexl@redhat.com>
* gtk/gtkimagemenuitem.[c]:
+2001-03-21 Alexander Larsson <alexl@redhat.com>
+
+ * gtk/gtkbutton.[ch]:
+ * gtk/gtkdialog.c:
+ Renamed gtk_button_new_stock() to gtk_button_new_from_stock() and
+ removed accel_group argument. Renamed gtk_button_new_accel() to
+ gtk_button_new_with_mnemonic() and removed accel_group argument.
+
+ * gtk/gtkcheckbutton.[ch]:
+ New function gtk_check_button_new_with_mnemonic().
+
+ * gtk/gtkentry.c:
+ Override activate_mnemonic and just grab focus.
+
+ * gtk/gtkitemfactory.c:
+ Don't add menu uline accel group, instead use mnemonics support.
+
+ * gtk/gtklabel.[ch]:
+ New support for mnemonics.
+
+ * gtk/gtkmarshal.list:
+ Needed BOOLEAN:BOOLEAN for activate_mnemonic.
+
+ * gtk/gtkmenu.[c]:
+ * gtkmenushell.c:
+ Use mnemonics instead of accel groups for uline
+ support in menu items.
+ Removed gtk_menu_get_uline_accel_group() and
+ gtk_menu_ensure_uline_accel_group().
+
+ * gtk/gtkmenuitem.c:
+ Override activate_mnemonic to handle switching between
+ menu items if there are collisions.
+
+ * gtk/gtknotebook.c:
+ Connect to activate_mnemonic on the tab_label, so that
+ activating it switches to that notebook page.
+
+ * gtk/gtkwidget.[ch]:
+ Add activate_mnemonic signal. New function
+ gtk_widget_activate_mnemonic() to emit it.
+ Default implementation does activate/grab_focus.
+
+ * gtk/gtkwindow.[ch]:
+ Add support for mnemonics in windows.
+ New functions:
+ gtk_window_add_mnemonic, gtk_window_remove_mnemonic,
+ gtk_window_activate_mnemonic, gtk_window_set_mnemonic_modifier
+
+ * gtk/testgtk.c:
+ Update to function name changes.
+
2001-03-21 Alexander Larsson <alexl@redhat.com>
* gtk/gtkimagemenuitem.[c]:
+2001-03-21 Alexander Larsson <alexl@redhat.com>
+
+ * gtk/gtkbutton.[ch]:
+ * gtk/gtkdialog.c:
+ Renamed gtk_button_new_stock() to gtk_button_new_from_stock() and
+ removed accel_group argument. Renamed gtk_button_new_accel() to
+ gtk_button_new_with_mnemonic() and removed accel_group argument.
+
+ * gtk/gtkcheckbutton.[ch]:
+ New function gtk_check_button_new_with_mnemonic().
+
+ * gtk/gtkentry.c:
+ Override activate_mnemonic and just grab focus.
+
+ * gtk/gtkitemfactory.c:
+ Don't add menu uline accel group, instead use mnemonics support.
+
+ * gtk/gtklabel.[ch]:
+ New support for mnemonics.
+
+ * gtk/gtkmarshal.list:
+ Needed BOOLEAN:BOOLEAN for activate_mnemonic.
+
+ * gtk/gtkmenu.[c]:
+ * gtkmenushell.c:
+ Use mnemonics instead of accel groups for uline
+ support in menu items.
+ Removed gtk_menu_get_uline_accel_group() and
+ gtk_menu_ensure_uline_accel_group().
+
+ * gtk/gtkmenuitem.c:
+ Override activate_mnemonic to handle switching between
+ menu items if there are collisions.
+
+ * gtk/gtknotebook.c:
+ Connect to activate_mnemonic on the tab_label, so that
+ activating it switches to that notebook page.
+
+ * gtk/gtkwidget.[ch]:
+ Add activate_mnemonic signal. New function
+ gtk_widget_activate_mnemonic() to emit it.
+ Default implementation does activate/grab_focus.
+
+ * gtk/gtkwindow.[ch]:
+ Add support for mnemonics in windows.
+ New functions:
+ gtk_window_add_mnemonic, gtk_window_remove_mnemonic,
+ gtk_window_activate_mnemonic, gtk_window_set_mnemonic_modifier
+
+ * gtk/testgtk.c:
+ Update to function name changes.
+
2001-03-21 Alexander Larsson <alexl@redhat.com>
* gtk/gtkimagemenuitem.[c]:
+2001-03-21 Alexander Larsson <alexl@redhat.com>
+
+ * gtk/gtkbutton.[ch]:
+ * gtk/gtkdialog.c:
+ Renamed gtk_button_new_stock() to gtk_button_new_from_stock() and
+ removed accel_group argument. Renamed gtk_button_new_accel() to
+ gtk_button_new_with_mnemonic() and removed accel_group argument.
+
+ * gtk/gtkcheckbutton.[ch]:
+ New function gtk_check_button_new_with_mnemonic().
+
+ * gtk/gtkentry.c:
+ Override activate_mnemonic and just grab focus.
+
+ * gtk/gtkitemfactory.c:
+ Don't add menu uline accel group, instead use mnemonics support.
+
+ * gtk/gtklabel.[ch]:
+ New support for mnemonics.
+
+ * gtk/gtkmarshal.list:
+ Needed BOOLEAN:BOOLEAN for activate_mnemonic.
+
+ * gtk/gtkmenu.[c]:
+ * gtkmenushell.c:
+ Use mnemonics instead of accel groups for uline
+ support in menu items.
+ Removed gtk_menu_get_uline_accel_group() and
+ gtk_menu_ensure_uline_accel_group().
+
+ * gtk/gtkmenuitem.c:
+ Override activate_mnemonic to handle switching between
+ menu items if there are collisions.
+
+ * gtk/gtknotebook.c:
+ Connect to activate_mnemonic on the tab_label, so that
+ activating it switches to that notebook page.
+
+ * gtk/gtkwidget.[ch]:
+ Add activate_mnemonic signal. New function
+ gtk_widget_activate_mnemonic() to emit it.
+ Default implementation does activate/grab_focus.
+
+ * gtk/gtkwindow.[ch]:
+ Add support for mnemonics in windows.
+ New functions:
+ gtk_window_add_mnemonic, gtk_window_remove_mnemonic,
+ gtk_window_activate_mnemonic, gtk_window_set_mnemonic_modifier
+
+ * gtk/testgtk.c:
+ Update to function name changes.
+
2001-03-21 Alexander Larsson <alexl@redhat.com>
* gtk/gtkimagemenuitem.[c]:
return button;
}
+/**
+ * gtk_button_new_from_stock:
+ * @stock_id: the name of the stock item
+ * @returns: a new #GtkButton
+ *
+ * Creates a new #GtkButton containing the image and text from a stock item.
+ * Some stock ids have preprocessor macros like #GTK_STOCK_BUTTON_OK and
+ * #GTK_STOCK_BUTTON_APPLY.
+ **/
GtkWidget*
-gtk_button_new_stock (const gchar *stock_id,
- GtkAccelGroup *accel_group)
+gtk_button_new_from_stock (const gchar *stock_id)
{
GtkWidget *button;
GtkStockItem item;
GtkWidget *label;
GtkWidget *image;
GtkWidget *hbox;
- guint keyval;
button = gtk_button_new ();
- label = gtk_label_new (NULL);
- keyval = gtk_label_parse_uline (GTK_LABEL (label),
- item.label);
-
- if (keyval && accel_group)
- {
- gtk_widget_add_accelerator (button,
- "clicked",
- accel_group,
- keyval,
- GDK_MOD1_MASK,
- GTK_ACCEL_LOCKED);
- }
-
- /* Also add the stock accelerator if one was specified. */
- if (item.keyval && accel_group)
- {
- gtk_widget_add_accelerator (button,
- "clicked",
- accel_group,
- item.keyval,
- item.modifier,
- GTK_ACCEL_LOCKED);
- }
+ label = gtk_label_new_with_mnemonic (item.label);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
hbox = gtk_hbox_new (FALSE, 0);
}
else
{
- button = gtk_button_new_accel (stock_id, accel_group);
+ button = gtk_button_new_with_mnemonic (stock_id);
}
return button;
}
+/**
+ * gtk_button_new_with_mnemonic:
+ * @label: The text of the button, with an underscore in front of the
+ * mnemonic character
+ * @returns: a new #GtkButton
+ *
+ * Creates a new #GtkButton containing a label.
+ * If characters in @label are preceded by an underscore, they are underlined
+ * indicating that they represent a keyboard accelerator called a mnemonic.
+ * Pressing Alt and that key activates the button.
+ **/
GtkWidget*
-gtk_button_new_accel (const gchar *uline_label,
- GtkAccelGroup *accel_group)
+gtk_button_new_with_mnemonic (const gchar *label)
{
GtkWidget *button;
- GtkWidget *label;
- guint keyval;
+ GtkWidget *label_widget;
button = gtk_button_new ();
- label = gtk_label_new (NULL);
- keyval = gtk_label_parse_uline (GTK_LABEL (label), uline_label);
+ label_widget = gtk_label_new_with_mnemonic (label);
- if (keyval && accel_group)
- {
- gtk_widget_add_accelerator (button,
- "clicked",
- accel_group,
- keyval,
- GDK_MOD1_MASK,
- GTK_ACCEL_LOCKED);
- }
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label_widget), button);
- gtk_container_add (GTK_CONTAINER (button), label);
- gtk_widget_show (label);
+ gtk_container_add (GTK_CONTAINER (button), label_widget);
+ gtk_widget_show (label_widget);
return button;
}
GtkType gtk_button_get_type (void) G_GNUC_CONST;
-GtkWidget* gtk_button_new (void);
-GtkWidget* gtk_button_new_with_label (const gchar *label);
-GtkWidget* gtk_button_new_stock (const gchar *stock_id,
- GtkAccelGroup *accel_group);
-GtkWidget* gtk_button_new_accel (const gchar *uline_label,
- GtkAccelGroup *accel_group);
-void gtk_button_pressed (GtkButton *button);
-void gtk_button_released (GtkButton *button);
-void gtk_button_clicked (GtkButton *button);
-void gtk_button_enter (GtkButton *button);
-void gtk_button_leave (GtkButton *button);
-void gtk_button_set_relief (GtkButton *button,
- GtkReliefStyle newstyle);
-GtkReliefStyle gtk_button_get_relief (GtkButton *button);
+GtkWidget* gtk_button_new (void);
+GtkWidget* gtk_button_new_with_label (const gchar *label);
+GtkWidget* gtk_button_new_from_stock (const gchar *stock_id);
+GtkWidget* gtk_button_new_with_mnemonic (const gchar *label);
+void gtk_button_pressed (GtkButton *button);
+void gtk_button_released (GtkButton *button);
+void gtk_button_clicked (GtkButton *button);
+void gtk_button_enter (GtkButton *button);
+void gtk_button_leave (GtkButton *button);
+void gtk_button_set_relief (GtkButton *button,
+ GtkReliefStyle newstyle);
+GtkReliefStyle gtk_button_get_relief (GtkButton *button);
#ifdef __cplusplus
return check_button;
}
+/**
+ * gtk_check_button_new_with_mnemonic:
+ * @label: The text of the button, with an underscore in front of the
+ * mnemonic character
+ * @returns: a new #GtkCheckButton
+ *
+ * Creates a new #GtkCheckButton containing a label.
+ * If characters in @label are preceded by an underscore, they are underlined
+ * indicating that they represent a keyboard accelerator called a mnemonic.
+ * Pressing Alt and that key activates the checkbutton.
+ **/
+GtkWidget*
+gtk_check_button_new_with_mnemonic (const gchar *label)
+{
+ GtkWidget *check_button;
+ GtkWidget *label_widget;
+
+ check_button = gtk_check_button_new ();
+ label_widget = gtk_label_new_with_mnemonic (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label_widget), check_button);
+
+ gtk_container_add (GTK_CONTAINER (check_button), label_widget);
+ gtk_widget_show (label_widget);
+
+ return check_button;
+}
+
+
/* This should only be called when toggle_button->draw_indicator
* is true.
*/
GtkType gtk_check_button_get_type (void) G_GNUC_CONST;
-GtkWidget* gtk_check_button_new (void);
-GtkWidget* gtk_check_button_new_with_label (const gchar *label);
+GtkWidget* gtk_check_button_new (void);
+GtkWidget* gtk_check_button_new_with_label (const gchar *label);
+GtkWidget* gtk_check_button_new_with_mnemonic (const gchar *label);
#ifdef __cplusplus
g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
g_return_val_if_fail (button_text != NULL, NULL);
- button = gtk_button_new_stock (button_text,
- gtk_window_get_default_accel_group (GTK_WINDOW (dialog)));
+ button = gtk_button_new_from_stock (button_text);
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
static void gtk_entry_update_primary_selection (GtkEntry *entry);
static void gtk_entry_popup_menu (GtkEntry *entry,
GdkEventButton *event);
+static gboolean gtk_entry_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling);
static GtkWidgetClass *parent_class = NULL;
widget_class->style_set = gtk_entry_style_set;
widget_class->direction_changed = gtk_entry_direction_changed;
widget_class->state_changed = gtk_entry_state_changed;
+ widget_class->activate_mnemonic = gtk_entry_activate_mnemonic;
widget_class->drag_motion = gtk_entry_drag_motion;
widget_class->drag_leave = gtk_entry_drag_leave;
gtk_signal_emit_by_name (GTK_OBJECT (entry), signal);
}
+
+static gboolean
+gtk_entry_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ gtk_widget_grab_focus (widget);
+ return TRUE;
+}
+
static void
append_action_signal (GtkEntry *entry,
GtkWidget *menu,
"GtkMisc::xalign", 0.0,
NULL);
- accel_key = gtk_label_parse_uline (GTK_LABEL (label), name);
-
- if (accel_key != GDK_VoidSymbol)
- {
- if (GTK_IS_MENU_BAR (parent))
- gtk_widget_add_accelerator (widget,
- "activate_item",
- ifactory->accel_group,
- accel_key, GDK_MOD1_MASK,
- GTK_ACCEL_LOCKED);
-
- if (GTK_IS_MENU (parent))
- gtk_widget_add_accelerator (widget,
- "activate_item",
- gtk_menu_ensure_uline_accel_group (GTK_MENU (parent)),
- accel_key, 0,
- GTK_ACCEL_LOCKED);
- }
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (label), name);
}
g_free (name);
#include <math.h>
#include <string.h>
#include "gtklabel.h"
+#include "gtksignal.h"
+#include "gtkwindow.h"
#include "gdk/gdkkeysyms.h"
#include "gtkclipboard.h"
#include "gdk/gdki18n.h"
#include <pango/pango.h>
#include "gtkintl.h"
+#include "gtkmenuitem.h"
+#include "gtknotebook.h"
struct _GtkLabelSelectionInfo
{
gint selection_end;
};
+
enum {
PROP_0,
PROP_LABEL,
PROP_PATTERN,
PROP_WRAP,
PROP_SELECTABLE,
- PROP_ACCEL_KEYVAL
+ PROP_MNEMONIC_KEYVAL
};
static void gtk_label_class_init (GtkLabelClass *klass);
static void gtk_label_set_property (GObject *object,
guint prop_id,
const GValue *value,
- GParamSpec *pspec,
- const gchar *trailer);
+ GParamSpec *pspec);
static void gtk_label_get_property (GObject *object,
guint prop_id,
GValue *value,
- GParamSpec *pspec,
- const gchar *trailer);
+ GParamSpec *pspec);
static void gtk_label_finalize (GObject *object);
static void gtk_label_size_request (GtkWidget *widget,
GtkRequisition *requisition);
const gchar *str,
gboolean with_uline);
static void gtk_label_recalculate (GtkLabel *label);
+static void gtk_label_hierarchy_changed (GtkWidget *widget);
static void gtk_label_create_window (GtkLabel *label);
static void gtk_label_destroy_window (GtkLabel *label);
gint anchor_index,
gint end_index);
+static gboolean gtk_label_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling);
+
static GtkMiscClass *parent_class = NULL;
widget_class->button_press_event = gtk_label_button_press;
widget_class->button_release_event = gtk_label_button_release;
widget_class->motion_notify_event = gtk_label_motion;
+ widget_class->hierarchy_changed = gtk_label_hierarchy_changed;
+ widget_class->activate_mnemonic = gtk_label_activate_mnemonic;
g_object_class_install_property (G_OBJECT_CLASS(object_class),
PROP_LABEL,
PROP_USE_UNDERLINE,
g_param_spec_boolean ("use_underline",
_("Use underline"),
- _("If set, an underline in the text indicates the next character should be used for the accelerator key"),
+ _("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"),
FALSE,
G_PARAM_READWRITE));
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
- PROP_ACCEL_KEYVAL,
- g_param_spec_uint ("accel_keyval",
- _("Accelerator key value"),
- _("The accelerator key for this label."),
+ PROP_MNEMONIC_KEYVAL,
+ g_param_spec_uint ("mnemonic_keyval",
+ _("Mnemonic accelerator key value"),
+ _("The mnemonic accelerator key for this label."),
0,
G_MAXUINT,
GDK_VoidSymbol,
G_PARAM_READABLE));
+
}
static void
gtk_label_set_property (GObject *object,
guint prop_id,
const GValue *value,
- GParamSpec *pspec,
- const gchar *trailer)
+ GParamSpec *pspec)
{
GtkLabel *label;
gtk_label_get_property (GObject *object,
guint prop_id,
GValue *value,
- GParamSpec *pspec,
- const gchar *trailer)
+ GParamSpec *pspec)
{
GtkLabel *label;
case PROP_SELECTABLE:
g_value_set_boolean (value, gtk_label_get_selectable (label));
break;
- case PROP_ACCEL_KEYVAL:
- g_value_set_uint (value, label->accel_keyval);
+ case PROP_MNEMONIC_KEYVAL:
+ g_value_set_uint (value, label->mnemonic_keyval);
break;
default:
label->use_underline = FALSE;
label->use_markup = FALSE;
- label->accel_keyval = GDK_VoidSymbol;
+ label->mnemonic_keyval = GDK_VoidSymbol;
label->layout = NULL;
label->text = NULL;
label->attrs = NULL;
+
+ label->mnemonic_widget = NULL;
+ label->mnemonic_window = NULL;
gtk_label_set_text (label, "");
}
+/**
+ * gtk_label_new:
+ * @str: The text of the label
+ * @returns: a new #GtkLabel
+ *
+ * Creates a new #GtkLabel, containing the text in @str.
+ **/
GtkWidget*
gtk_label_new (const gchar *str)
{
}
/**
- * gtk_label_get_accel_keyval:
+ * gtk_label_new_with_mnemonic:
+ * @str: The text of the label, with an underscore in front of the
+ * mnemonic character
+ * @returns: a new #GtkLabel
+ *
+ * Creates a new #GtkLabel, containing the text in @str.
+ *
+ * If characters in @str are preceded by an underscore, they are underlined
+ * indicating that they represent a keyboard accelerator called a mnemonic.
+ * The mnemonic key can be used to activate another widget, chosen automatically,
+ * or explicitly using @gtk_label_set_mnemonic_widget.
+ **/
+GtkWidget*
+gtk_label_new_with_mnemonic (const gchar *str)
+{
+ GtkLabel *label;
+
+ label = gtk_type_new (GTK_TYPE_LABEL);
+
+ if (str && *str)
+ gtk_label_set_text_with_mnemonic (label, str);
+
+ return GTK_WIDGET (label);
+}
+
+static gboolean
+gtk_label_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ GtkWidget *parent;
+
+ if (GTK_LABEL (widget)->mnemonic_widget)
+ return gtk_widget_activate_mnemonic (GTK_LABEL (widget)->mnemonic_widget, group_cycling);
+
+ /* Try to find the widget to activate by traversing the widget
+ * hierarachy.
+ */
+
+ parent = widget->parent;
+ while (parent)
+ {
+ if (GTK_WIDGET_CAN_FOCUS (parent) ||
+ (!group_cycling && GTK_WIDGET_GET_CLASS (parent)->activate_signal) ||
+ (parent->parent && GTK_IS_NOTEBOOK (parent->parent)) ||
+ (GTK_IS_MENU_ITEM (parent)))
+ return gtk_widget_activate_mnemonic (parent, group_cycling);
+ parent = parent->parent;
+ }
+
+ g_warning ("Couldn't find a target for a mnemonic activation.");
+ gdk_beep ();
+
+ return FALSE;
+}
+
+static void
+gtk_label_setup_mnemonic (GtkLabel *label, guint last_key)
+{
+ GtkWidget *toplevel;
+
+ if ((last_key != GDK_VoidSymbol) && label->mnemonic_window)
+ gtk_window_remove_mnemonic (label->mnemonic_window,
+ last_key,
+ GTK_WIDGET (label));
+
+ if (label->mnemonic_keyval == GDK_VoidSymbol)
+ return;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
+
+ if (GTK_IS_WINDOW (toplevel))
+ {
+ gtk_window_add_mnemonic (GTK_WINDOW (toplevel),
+ label->mnemonic_keyval,
+ GTK_WIDGET (label));
+ label->mnemonic_window = GTK_WINDOW (toplevel);
+ }
+}
+
+static void
+gtk_label_hierarchy_changed (GtkWidget *widget)
+{
+ GtkLabel *label = GTK_LABEL (widget);
+
+ gtk_label_setup_mnemonic (label, label->mnemonic_keyval);
+}
+
+
+/**
+ * gtk_label_set_mnemonic_widget:
+ * @label: a #GtkLabel
+ * @widget: the target #GtkWidget
+ *
+ * If the label has been set so that it has an mnemonic key (using i.e.
+ * @gtk_label_set_markup_with_mnemonic, @gtk_label_set_text_with_mnemonic,
+ * @gtk_label_new_with_mnemonic or the use_underline property) the label can be
+ * associated with a widget that is the target of the mnemonic. When the label
+ * is inside a widget (like a #GtkButton or a #GtkNotebook tab) it is automatically
+ * associated with the correct widget, but sometimes (i.e. when the target is
+ * a #GtkEntry next to the label) you need to set it explicitly using this
+ * function.
+ *
+ * The target widget will be accelerated by emitting "activate_mnemonic" on it.
+ * The default handler for this signal will activate the widget if there are no
+ * mnemonic collisions and toggle focus between the colliding widgets otherwise.
+ **/
+void
+gtk_label_set_mnemonic_widget (GtkLabel *label,
+ GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_LABEL (label));
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ label->mnemonic_widget = widget;
+}
+
+
+/**
+ * gtk_label_get_mnemonic_keyval:
* @label: a #GtkLabel
* @Returns: GDK keyval usable for accelerators, or GDK_VoidSymbol
*
- * If the label text was set using gtk_label_set_markup_with_accel,
- * gtk_label_parse_uline, or using the use_underline property this function
- * returns the keyval for the first underlined accelerator.
+ * If the label has been set so that it has an mnemonic key this function
+ * returns the keyval used for the mnemonic accelerator. If there is no
+ * mnemonic set up it returns #GDK_VoidSymbol.
**/
guint
-gtk_label_get_accel_keyval (GtkLabel *label)
+gtk_label_get_mnemonic_keyval (GtkLabel *label)
{
g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
- return label->accel_keyval;
+ return label->mnemonic_keyval;
}
static void
}
-/* Calculates text, attrs and accel_keyval from
+/* Calculates text, attrs and mnemonic_keyval from
* label, use_underline and use_markup */
static void
gtk_label_recalculate (GtkLabel *label)
}
if (!label->use_underline)
- label->accel_keyval = GDK_VoidSymbol;
+ {
+ guint keyval = label->mnemonic_keyval;
+ label->mnemonic_keyval = GDK_VoidSymbol;
+ gtk_label_setup_mnemonic (label, keyval);
+ }
gtk_label_clear_layout (label);
gtk_widget_queue_resize (GTK_WIDGET (label));
}
+/**
+ * gtk_label_set_text:
+ * label: a #GtkLabel
+ * str: a string
+ *
+ * Sets the text of the label to @str.
+ *
+ * This will also clear any previously set mnemonic accelerators.
+ **/
void
gtk_label_set_text (GtkLabel *label,
const gchar *str)
}
if (accel_char != 0)
- label->accel_keyval = gdk_keyval_to_lower (gdk_unicode_to_keyval (accel_char));
+ label->mnemonic_keyval = gdk_keyval_to_lower (gdk_unicode_to_keyval (accel_char));
else
- label->accel_keyval = GDK_VoidSymbol;
+ label->mnemonic_keyval = GDK_VoidSymbol;
}
/**
}
/**
- * gtk_label_set_markup_with_accel:
+ * gtk_label_set_markup_with_mnemonic:
* @label: a #GtkLabel
* @str: a markup string (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
*
* Parses @str which is marked up with the Pango text markup language,
* setting the label's text and attribute list based on the parse results.
* If characters in @str are preceded by an underscore, they are underlined
- * indicating that they represent a keyboard accelerator, and the GDK
- * keyval for the first underlined accelerator is returned. If there are
- * no underlines in the text, GDK_VoidSymbol will be returned.
+ * indicating that they represent a keyboard accelerator called a mnemonic.
*
- * Return value: GDK keyval for accelerator
+ * The mnemonic key can be used to activate another widget, chosen automatically,
+ * or explicitly using @gtk_label_set_mnemonic_widget.
**/
-guint
-gtk_label_set_markup_with_accel (GtkLabel *label,
- const gchar *str)
+void
+gtk_label_set_markup_with_mnemonic (GtkLabel *label,
+ const gchar *str)
{
- g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
+ guint last_keyval;
+ g_return_if_fail (GTK_IS_LABEL (label));
+ last_keyval = label->mnemonic_keyval;
gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
gtk_label_set_use_markup_internal (label, TRUE);
gtk_label_set_use_underline_internal (label, TRUE);
gtk_label_recalculate (label);
- return label->accel_keyval;
+ gtk_label_setup_mnemonic (label, last_keyval);
}
/**
pango_attr_list_unref (label->attrs);
g_free (label->select_info);
-
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
g_free (pattern);
- label->accel_keyval = accel_key;
+ label->mnemonic_keyval = accel_key;
}
guint
gtk_label_parse_uline (GtkLabel *label,
const gchar *str)
{
+ guint keyval;
+ guint orig_keyval;
+
g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
g_return_val_if_fail (str != NULL, GDK_VoidSymbol);
+ orig_keyval = label->mnemonic_keyval;
+
gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
gtk_label_set_use_markup_internal (label, FALSE);
gtk_label_set_use_underline_internal (label, TRUE);
gtk_label_recalculate (label);
- return label->accel_keyval;
+
+ keyval = label->mnemonic_keyval;
+ label->mnemonic_keyval = GDK_VoidSymbol;
+
+ gtk_label_setup_mnemonic (label, orig_keyval);
+
+ return keyval;
+}
+
+/**
+ * gtk_label_set_text_with_mnemonic:
+ * @label: a #GtkLabel
+ * @str: a string
+ *
+ * Sets the label's text from the string @str.
+ * If characters in @str are preceded by an underscore, they are underlined
+ * indicating that they represent a keyboard accelerator called a mnemonic.
+ * The mnemonic key can be used to activate another widget, chosen automatically,
+ * or explicitly using @gtk_label_set_mnemonic_widget.
+ **/
+void
+gtk_label_set_text_with_mnemonic (GtkLabel *label,
+ const gchar *str)
+{
+ guint last_keyval;
+
+ g_return_if_fail (GTK_IS_LABEL (label));
+ g_return_if_fail (str != NULL);
+
+ last_keyval = label->mnemonic_keyval;
+
+ gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
+ gtk_label_set_use_markup_internal (label, FALSE);
+ gtk_label_set_use_underline_internal (label, TRUE);
+
+ gtk_label_recalculate (label);
+
+ gtk_label_setup_mnemonic (label, last_keyval);
}
if (label->text && label->select_info)
{
- GtkClipboard *clipboard;
-
if (start_offset < 0)
start_offset = 0;
#include <gdk/gdk.h>
#include <gtk/gtkmisc.h>
+#include <gtk/gtkwindow.h>
#ifdef __cplusplus
guint use_underline : 1;
guint use_markup : 1;
- guint accel_keyval;
+ guint mnemonic_keyval;
gchar *text;
PangoAttrList *attrs;
PangoLayout *layout;
+ GtkWidget *mnemonic_widget;
+ GtkWindow *mnemonic_window;
+
GtkLabelSelectionInfo *select_info;
};
GtkMiscClass parent_class;
};
-GtkType gtk_label_get_type (void) G_GNUC_CONST;
-GtkWidget *gtk_label_new (const char *str);
+GtkType gtk_label_get_type (void) G_GNUC_CONST;
+GtkWidget *gtk_label_new (const char *str);
+GtkWidget *gtk_label_new_with_mnemonic (const char *str);
void gtk_label_set_text (GtkLabel *label,
const char *str);
void gtk_label_set_markup (GtkLabel *label,
const gchar *str);
-guint gtk_label_set_markup_with_accel (GtkLabel *label,
- const gchar *str);
-
-guint gtk_label_get_accel_keyval (GtkLabel *label);
-void gtk_label_set_justify (GtkLabel *label,
- GtkJustification jtype);
-void gtk_label_set_pattern (GtkLabel *label,
- const gchar *pattern);
-void gtk_label_set_line_wrap (GtkLabel *label,
- gboolean wrap);
+void gtk_label_set_markup_with_mnemonic (GtkLabel *label,
+ const gchar *str);
+
+guint gtk_label_get_mnemonic_keyval (GtkLabel *label);
+void gtk_label_set_justify (GtkLabel *label,
+ GtkJustification jtype);
+void gtk_label_set_pattern (GtkLabel *label,
+ const gchar *pattern);
+void gtk_label_set_line_wrap (GtkLabel *label,
+ gboolean wrap);
/* Convenience function to set the name and pattern by parsing
* a string with embedded underscores, and return the appropriate
* key symbol for the accelerator.
*/
-guint gtk_label_parse_uline (GtkLabel *label,
- const gchar *string);
+guint gtk_label_parse_uline (GtkLabel *label,
+ const gchar *string);
+void gtk_label_set_text_with_mnemonic (GtkLabel *label,
+ const gchar *string);
+void gtk_label_set_mnemonic_widget (GtkLabel *label,
+ GtkWidget *widget);
void gtk_label_set_selectable (GtkLabel *label,
gboolean setting);
BOOLEAN:OBJECT,INT,INT,UINT
BOOLEAN:OBJECT,STRING,STRING,BOXED
BOOLEAN:VOID
+BOOLEAN:BOOLEAN
ENUM:ENUM
INT:OBJECT,BOXED,BOXED
INT:POINTER
BOOLEAN:OBJECT,INT,INT,UINT
BOOLEAN:OBJECT,STRING,STRING,BOXED
BOOLEAN:VOID
+BOOLEAN:BOOLEAN
ENUM:ENUM
INT:OBJECT,BOXED,BOXED
INT:POINTER
static GtkMenuShellClass *parent_class = NULL;
static const gchar *attach_data_key = "gtk-menu-attach-data";
-static GQuark quark_uline_accel_group = 0;
GtkType
gtk_menu_get_type (void)
NULL);
gtk_window_set_policy (GTK_WINDOW (menu->toplevel),
FALSE, FALSE, TRUE);
+ gtk_window_set_mnemonic_modifier (GTK_WINDOW (menu->toplevel), 0);
/* Refloat the menu, so that reference counting for the menu isn't
* affected by it being a child of the toplevel
return menu->accel_group;
}
-GtkAccelGroup*
-gtk_menu_ensure_uline_accel_group (GtkMenu *menu)
-{
- GtkAccelGroup *accel_group;
-
- g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
-
- if (!quark_uline_accel_group)
- quark_uline_accel_group = g_quark_from_static_string ("GtkMenu-uline-accel-group");
-
- accel_group = gtk_object_get_data_by_id (GTK_OBJECT (menu), quark_uline_accel_group);
- if (!accel_group)
- {
- accel_group = gtk_accel_group_new ();
- gtk_accel_group_attach (accel_group, GTK_OBJECT (menu));
- gtk_object_set_data_by_id_full (GTK_OBJECT (menu),
- quark_uline_accel_group,
- accel_group,
- (GtkDestroyNotify) gtk_accel_group_unref);
- }
-
- return accel_group;
-}
-
-GtkAccelGroup*
-gtk_menu_get_uline_accel_group (GtkMenu *menu)
-{
- g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
-
- return gtk_object_get_data_by_id (GTK_OBJECT (menu), quark_uline_accel_group);
-}
-
void
gtk_menu_reposition (GtkMenu *menu)
{
NULL);
gtk_window_set_type_hint (GTK_WINDOW (menu->tearoff_window),
GDK_WINDOW_TYPE_HINT_MENU);
+ gtk_window_set_mnemonic_modifier (GTK_WINDOW (menu->tearoff_window), 0);
gtk_widget_set_app_paintable (menu->tearoff_window, TRUE);
gtk_signal_connect (GTK_OBJECT (menu->tearoff_window),
"event",
(delete ||
(gtk_accelerator_valid (event->keyval, event->state) &&
(event->state ||
- !gtk_menu_get_uline_accel_group (GTK_MENU (menu_shell)) ||
(event->keyval >= GDK_F1 && event->keyval <= GDK_F35)))))
{
GtkMenuItem *menu_item;
GtkAccelGroup *accel_group);
GtkAccelGroup* gtk_menu_get_accel_group (GtkMenu *menu);
-/* get the accelerator group that is used internally by the menu for
- * underline accelerators while the menu is popped up.
- */
-GtkAccelGroup* gtk_menu_get_uline_accel_group (GtkMenu *menu);
-GtkAccelGroup* gtk_menu_ensure_uline_accel_group (GtkMenu *menu);
-
/* A reference count is kept for a widget when it is attached to
* a particular widget. This is typically a menu item; it may also
gint *requisition);
static void gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
gint allocation);
+static gboolean gtk_menu_item_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling);
static gint gtk_menu_item_select_timeout (gpointer data);
static void gtk_menu_item_popup_submenu (gpointer data);
GtkCallback callback,
gpointer callback_data);
+
static GtkItemClass *parent_class;
static guint menu_item_signals[LAST_SIGNAL] = { 0 };
static guint32 last_submenu_deselect_time = 0;
widget_class->expose_event = gtk_menu_item_expose;
widget_class->show_all = gtk_menu_item_show_all;
widget_class->hide_all = gtk_menu_item_hide_all;
+ widget_class->activate_mnemonic = gtk_menu_item_activate_mnemonic;
container_class->forall = gtk_menu_item_forall;
gtk_widget_draw (GTK_WIDGET (menu_item), NULL);
}
+static gboolean
+gtk_menu_item_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ if (group_cycling)
+ {
+ if (widget->parent &&
+ GTK_IS_MENU_SHELL (widget->parent))
+ gtk_menu_shell_select_item (GTK_MENU_SHELL (widget->parent),
+ widget);
+
+ }
+ else
+ gtk_signal_emit (GTK_OBJECT (widget), menu_item_signals[ACTIVATE_ITEM]);
+
+ return TRUE;
+}
+
+
static void
gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
{
#include "gtktearoffmenuitem.h" /* FIXME */
#include "gtkmenushell.h"
#include "gtksignal.h"
-
+#include "gtkwindow.h"
#define MENU_SHELL_TIMEOUT 500
GdkEventKey *event)
{
GtkMenuShell *menu_shell;
+ GtkWidget *toplevel;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_MENU_SHELL (widget), FALSE);
event->state))
return TRUE;
+ toplevel = gtk_widget_get_toplevel (widget);
+ if (GTK_IS_WINDOW (toplevel) &&
+ gtk_window_activate_mnemonic (GTK_WINDOW (toplevel),
+ event->keyval,
+ event->state))
+ return TRUE;
+
if (gtk_accel_groups_activate (GTK_OBJECT (widget), event->keyval, event->state))
return TRUE;
GtkRequisition requisition;
GtkAllocation allocation;
+
+ guint activate_mnemonic_signal;
};
#ifdef G_DISABLE_CHECKS
if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
need_resize = TRUE;
+ if (page->tab_label && page->activate_mnemonic_signal)
+ gtk_signal_disconnect (page->tab_label,
+ page->activate_mnemonic_signal);
+
gtk_widget_unparent (page->child);
if (page->tab_label)
gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
}
+
+static gint
+gtk_notebook_page_compare_tab (gconstpointer a,
+ gconstpointer b)
+{
+ return (((GtkNotebookPage *) a)->tab_label != b);
+}
+
+static gboolean
+gtk_notebook_activate_mnemonic_switch_page (GtkWidget *child,
+ gboolean overload,
+ gpointer data)
+{
+ GtkNotebook *notebook = GTK_NOTEBOOK (data);
+ GtkNotebookPage *page;
+ GList *list;
+
+ list = g_list_find_custom (notebook->children, child,
+ gtk_notebook_page_compare_tab);
+ if (!list)
+ return TRUE;
+
+
+ page = list->data;
+
+ gtk_notebook_switch_page (notebook, page, -1);
+ return TRUE;
+}
+
/**
* gtk_notebook_insert_page_menu:
* @notebook: a #GtkNotebook
page->allocation.height = 0;
page->default_menu = FALSE;
page->default_tab = FALSE;
+ page->activate_mnemonic_signal = 0;
nchildren = g_list_length (notebook->children);
if ((position < 0) || (position > nchildren))
gtk_widget_hide (tab_label);
}
}
+
+ if (tab_label)
+ page->activate_mnemonic_signal =
+ gtk_signal_connect (GTK_OBJECT (tab_label),
+ "activate_mnemonic",
+ (GtkSignalFunc) gtk_notebook_activate_mnemonic_switch_page,
+ notebook);
}
/**
DIRECTION_CHANGED,
ADD_ACCELERATOR,
REMOVE_ACCELERATOR,
+ ACTIVATE_MNEMONIC,
GRAB_FOCUS,
EVENT,
BUTTON_PRESS_EVENT,
static void gtk_widget_propagate_hierarchy_changed (GtkWidget *widget,
gpointer client_data);
+static gboolean gtk_widget_real_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling);
static GtkWidgetAuxInfo* gtk_widget_aux_info_new (void);
static void gtk_widget_aux_info_destroy (GtkWidgetAuxInfo *aux_info);
klass->direction_changed = gtk_widget_direction_changed;
klass->add_accelerator = (void*) gtk_accel_group_handle_add;
klass->remove_accelerator = (void*) gtk_accel_group_handle_remove;
+ klass->activate_mnemonic = gtk_widget_real_activate_mnemonic;
klass->grab_focus = gtk_widget_real_grab_focus;
klass->event = NULL;
klass->button_press_event = NULL;
widget_signals[REMOVE_ACCELERATOR] =
gtk_accel_group_create_remove (GTK_CLASS_TYPE (object_class), GTK_RUN_LAST,
GTK_SIGNAL_OFFSET (GtkWidgetClass, remove_accelerator));
+ widget_signals[ACTIVATE_MNEMONIC] =
+ gtk_signal_new ("activate_mnemonic",
+ GTK_RUN_LAST,
+ GTK_CLASS_TYPE (object_class),
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, activate_mnemonic),
+ gtk_marshal_BOOLEAN__BOOLEAN,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_BOOL);
widget_signals[GRAB_FOCUS] =
gtk_signal_new ("grab_focus",
GTK_RUN_LAST | GTK_RUN_ACTION,
return 0;
}
+gboolean
+gtk_widget_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ gboolean handled = FALSE;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ return TRUE;
+
+ gtk_signal_emit_by_name (GTK_OBJECT (widget),
+ "activate_mnemonic",
+ group_cycling,
+ &handled);
+ return handled;
+}
+
+static gboolean
+gtk_widget_real_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ if (group_cycling)
+ gtk_widget_grab_focus (widget);
+ else if (!group_cycling)
+ gtk_widget_activate (widget);
+ return TRUE;
+}
+
+
static gint
gtk_widget_real_key_press_event (GtkWidget *widget,
GdkEventKey *event)
guint accel_key,
GdkModifierType accel_mods);
+ /* Mnemonics */
+ gboolean (* activate_mnemonic) (GtkWidget *widget,
+ gboolean group_cycling);
+
/* explicit focus */
void (* grab_focus) (GtkWidget *widget);
void gtk_widget_lock_accelerators (GtkWidget *widget);
void gtk_widget_unlock_accelerators (GtkWidget *widget);
gboolean gtk_widget_accelerators_locked (GtkWidget *widget);
+gboolean gtk_widget_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling);
gboolean gtk_widget_event (GtkWidget *widget,
GdkEvent *event);
gint gtk_widget_send_expose (GtkWidget *widget,
GtkWindowLastGeometryInfo last;
} GtkWindowGeometryInfo;
+typedef struct {
+ GtkWindow *window;
+ guint keyval;
+
+ GSList *targets;
+} GtkWindowMnemonic;
+
+
static void gtk_window_class_init (GtkWindowClass *klass);
static void gtk_window_init (GtkWindow *window);
static void gtk_window_shutdown (GObject *object);
static GSList *toplevel_list = NULL;
+static GHashTable *mnemonic_hash_table = NULL;
static GtkBinClass *parent_class = NULL;
static guint window_signals[LAST_SIGNAL] = { 0 };
GValue *value,
GParamSpec *pspec);
+
+static guint
+mnemonic_hash (gconstpointer key)
+{
+ const GtkWindowMnemonic *k;
+ guint h;
+
+ k = (GtkWindowMnemonic *)key;
+
+ h = (gulong) k->window;
+ h ^= k->keyval << 16;
+ h ^= k->keyval >> 16;
+
+ return h;
+}
+
+static gboolean
+mnemonic_equal (gconstpointer a, gconstpointer b)
+{
+ const GtkWindowMnemonic *ka;
+ const GtkWindowMnemonic *kb;
+
+ ka = (GtkWindowMnemonic *)a;
+ kb = (GtkWindowMnemonic *)b;
+
+ return
+ (ka->window == kb->window) &&
+ (ka->keyval == kb->keyval);
+}
+
GtkType
gtk_window_get_type (void)
{
gtk_marshal_BOOLEAN__BOXED,
GTK_TYPE_BOOL, 1,
GTK_TYPE_GDK_EVENT);
+
+
+ if (!mnemonic_hash_table)
+ mnemonic_hash_table = g_hash_table_new (mnemonic_hash,
+ mnemonic_equal);
}
static void
window->frame_bottom = 0;
window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
window->decorated = TRUE;
+ window->mnemonic_modifier = GDK_MOD1_MASK;
gtk_widget_ref (GTK_WIDGET (window));
gtk_object_sink (GTK_OBJECT (window));
return group;
}
+void
+gtk_window_add_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target)
+{
+ GtkWindowMnemonic key;
+ GtkWindowMnemonic *mnemonic;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_WIDGET (target));
+
+ key.window = window;
+ key.keyval = keyval;
+
+ mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
+
+ if (mnemonic)
+ mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
+ else
+ {
+ mnemonic = g_new (GtkWindowMnemonic, 1);
+ *mnemonic = key;
+ mnemonic->targets = g_slist_prepend (NULL, target);
+ g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
+ }
+}
+
+void
+gtk_window_remove_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target)
+{
+ GtkWindowMnemonic key;
+ GtkWindowMnemonic *mnemonic;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_WIDGET (target));
+
+ key.window = window;
+ key.keyval = keyval;
+
+ mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
+
+ g_assert (mnemonic);
+
+ if (mnemonic)
+ {
+ mnemonic->targets = g_slist_remove (mnemonic->targets, target);
+
+ if (mnemonic->targets == NULL)
+ {
+ g_hash_table_remove (mnemonic_hash_table, mnemonic);
+ g_free (mnemonic);
+ }
+ }
+}
+
+gboolean
+gtk_window_activate_mnemonic (GtkWindow *window,
+ guint keyval,
+ GdkModifierType modifier)
+{
+ GtkWindowMnemonic key;
+ GtkWindowMnemonic *mnemonic;
+ GSList *list;
+ GtkWidget *widget, *chosen_widget;
+ gboolean overloaded;
+
+ g_return_val_if_fail (window != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+ if (modifier != window->mnemonic_modifier)
+ return FALSE;
+
+ key.window = window;
+ key.keyval = keyval;
+
+ mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
+
+ if (!mnemonic)
+ return FALSE;
+
+ overloaded = FALSE;
+ chosen_widget = NULL;
+ list = mnemonic->targets;
+ while (list)
+ {
+ widget = GTK_WIDGET (list->data);
+
+ if (GTK_WIDGET_IS_SENSITIVE (widget) &&
+ GTK_WIDGET_MAPPED (widget))
+ {
+ if (chosen_widget)
+ {
+ overloaded = TRUE;
+ break;
+ }
+ else
+ chosen_widget = widget;
+ }
+ list = g_slist_next (list);
+ }
+
+ if (chosen_widget)
+ {
+ /* For round robin we put the activated entry on
+ * the end of the list after activation */
+ mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
+ mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
+ return gtk_widget_activate_mnemonic (chosen_widget, overloaded);
+ }
+ return FALSE;
+}
+
+void
+gtk_window_set_mnemonic_modifier (GtkWindow *window,
+ GdkModifierType modifier)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ window->mnemonic_modifier = modifier;
+}
+
void
gtk_window_set_position (GtkWindow *window,
GtkWindowPosition position)
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
+static gboolean
+gtk_window_mnemonic_hash_remove (gpointer key,
+ gpointer value,
+ gpointer user)
+{
+ GtkWindowMnemonic *mnemonic = key;
+ GtkWindow *window = user;
+
+ if (mnemonic->window == window)
+ {
+ g_slist_free (mnemonic->targets);
+ g_free (mnemonic);
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
static void
gtk_window_finalize (GObject *object)
{
g_free (window->wmclass_name);
g_free (window->wmclass_class);
+ g_hash_table_foreach_remove (mnemonic_hash_table,
+ gtk_window_mnemonic_hash_remove,
+ window);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
{
handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
}
-
+
+ if (!handled)
+ handled = gtk_window_activate_mnemonic (window,
+ event->keyval,
+ event->state);
+
if (!handled)
handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
guint frame_top;
guint frame_right;
guint frame_bottom;
+
+ GdkModifierType mnemonic_modifier;
};
struct _GtkWindowClass
/* Get the "built-in" accel group (convenience thing) */
GtkAccelGroup* gtk_window_get_default_accel_group (GtkWindow *window);
+void gtk_window_add_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target);
+void gtk_window_remove_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target);
+gboolean gtk_window_activate_mnemonic (GtkWindow *window,
+ guint keyval,
+ GdkModifierType modifier);
+void gtk_window_set_mnemonic_modifier (GtkWindow *window,
+ GdkModifierType modifier);
+
+
void gtk_window_present (GtkWindow *window);
void gtk_window_iconify (GtkWindow *window);
void gtk_window_deiconify (GtkWindow *window);
gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
button[0] = gtk_button_new_with_label ("button1");
- button[1] = gtk_button_new_accel ("_button2", accel_group);
+ button[1] = gtk_button_new_with_mnemonic ("_button2");
button[2] = gtk_button_new_with_label ("button3");
- button[3] = gtk_button_new_stock (GTK_STOCK_BUTTON_OK, NULL);
+ button[3] = gtk_button_new_from_stock (GTK_STOCK_BUTTON_OK);
button[4] = gtk_button_new_with_label ("button5");
button[5] = gtk_button_new_with_label ("button6");
button[6] = gtk_button_new_with_label ("button7");
- button[7] = gtk_button_new_stock (GTK_STOCK_BUTTON_CLOSE, accel_group);
+ button[7] = gtk_button_new_from_stock (GTK_STOCK_BUTTON_CLOSE);
button[8] = gtk_button_new_with_label ("button9");
gtk_signal_connect (GTK_OBJECT (button[0]), "clicked",
if (!window)
{
- guint keyval;
-
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC(gtk_widget_destroyed),
/* There's also a gtk_label_set_markup() without accel if you
* don't have an accelerator key
*/
- keyval =
- gtk_label_set_markup_with_accel (GTK_LABEL (label),
- "This <span foreground=\"blue\" background=\"orange\">label</span> has "
- "<b>markup</b> _such as "
- "<big><i>Big Italics</i></big>\n"
- "<tt>Monospace font</tt>\n"
- "<u>Underline!</u>\n"
- "foo\n"
- "<span foreground=\"green\" background=\"red\">Ugly colors</span>\n"
- "and nothing on this line,\n"
- "or this.\n"
- "or this either\n"
- "or even on this one\n"
- "la <big>la <big>la <big>la <big>la</big></big></big></big>\n"
- "but this _word is <span foreground=\"purple\"><big>purple</big></span>\n"
- "<span underline=\"double\">We like <sup>superscript</sup> and <sub>subscript</sub> too</span>");
-
- g_return_if_fail (keyval == GDK_s);
+ gtk_label_set_markup_with_mnemonic (GTK_LABEL (label),
+ "This <span foreground=\"blue\" background=\"orange\">label</span> has "
+ "<b>markup</b> _such as "
+ "<big><i>Big Italics</i></big>\n"
+ "<tt>Monospace font</tt>\n"
+ "<u>Underline!</u>\n"
+ "foo\n"
+ "<span foreground=\"green\" background=\"red\">Ugly colors</span>\n"
+ "and nothing on this line,\n"
+ "or this.\n"
+ "or this either\n"
+ "or even on this one\n"
+ "la <big>la <big>la <big>la <big>la</big></big></big></big>\n"
+ "but this _word is <span foreground=\"purple\"><big>purple</big></span>\n"
+ "<span underline=\"double\">We like <sup>superscript</sup> and <sub>subscript</sub> too</span>");
+
+ g_assert (gtk_label_get_mnemonic_keyval (GTK_LABEL (label)) == GDK_s);
gtk_container_add (GTK_CONTAINER (frame), label);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
button[0] = gtk_button_new_with_label ("button1");
- button[1] = gtk_button_new_accel ("_button2", accel_group);
+ button[1] = gtk_button_new_with_mnemonic ("_button2");
button[2] = gtk_button_new_with_label ("button3");
- button[3] = gtk_button_new_stock (GTK_STOCK_BUTTON_OK, NULL);
+ button[3] = gtk_button_new_from_stock (GTK_STOCK_BUTTON_OK);
button[4] = gtk_button_new_with_label ("button5");
button[5] = gtk_button_new_with_label ("button6");
button[6] = gtk_button_new_with_label ("button7");
- button[7] = gtk_button_new_stock (GTK_STOCK_BUTTON_CLOSE, accel_group);
+ button[7] = gtk_button_new_from_stock (GTK_STOCK_BUTTON_CLOSE);
button[8] = gtk_button_new_with_label ("button9");
gtk_signal_connect (GTK_OBJECT (button[0]), "clicked",
if (!window)
{
- guint keyval;
-
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC(gtk_widget_destroyed),
/* There's also a gtk_label_set_markup() without accel if you
* don't have an accelerator key
*/
- keyval =
- gtk_label_set_markup_with_accel (GTK_LABEL (label),
- "This <span foreground=\"blue\" background=\"orange\">label</span> has "
- "<b>markup</b> _such as "
- "<big><i>Big Italics</i></big>\n"
- "<tt>Monospace font</tt>\n"
- "<u>Underline!</u>\n"
- "foo\n"
- "<span foreground=\"green\" background=\"red\">Ugly colors</span>\n"
- "and nothing on this line,\n"
- "or this.\n"
- "or this either\n"
- "or even on this one\n"
- "la <big>la <big>la <big>la <big>la</big></big></big></big>\n"
- "but this _word is <span foreground=\"purple\"><big>purple</big></span>\n"
- "<span underline=\"double\">We like <sup>superscript</sup> and <sub>subscript</sub> too</span>");
-
- g_return_if_fail (keyval == GDK_s);
+ gtk_label_set_markup_with_mnemonic (GTK_LABEL (label),
+ "This <span foreground=\"blue\" background=\"orange\">label</span> has "
+ "<b>markup</b> _such as "
+ "<big><i>Big Italics</i></big>\n"
+ "<tt>Monospace font</tt>\n"
+ "<u>Underline!</u>\n"
+ "foo\n"
+ "<span foreground=\"green\" background=\"red\">Ugly colors</span>\n"
+ "and nothing on this line,\n"
+ "or this.\n"
+ "or this either\n"
+ "or even on this one\n"
+ "la <big>la <big>la <big>la <big>la</big></big></big></big>\n"
+ "but this _word is <span foreground=\"purple\"><big>purple</big></span>\n"
+ "<span underline=\"double\">We like <sup>superscript</sup> and <sub>subscript</sub> too</span>");
+
+ g_assert (gtk_label_get_mnemonic_keyval (GTK_LABEL (label)) == GDK_s);
gtk_container_add (GTK_CONTAINER (frame), label);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);